package com.glq1218.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.glq1218.article.bo.ArticleBO;
import com.glq1218.article.entity.Article;
import com.glq1218.domain.*;
import com.glq1218.role.mapper.RoleMapper;
import com.glq1218.user.bo.AddUserBO;
import com.glq1218.user.bo.QueryUserBO;
import com.glq1218.user.bo.UpdateUserBO;
import com.glq1218.user.bo.UserBO;
import com.glq1218.user.entity.User;
import com.glq1218.user.mapper.UserMapper;
import com.glq1218.user.service.UserService;
import com.glq1218.util.BeanCopyUtils;
import com.glq1218.util.ServiceUtils;
import com.glq1218.util.SortUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 用户表(User)表服务实现类
 *
 * @author glq1218
 * @since 2023-04-10 09:51:46
 */
@Slf4j
@Service("userService")
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    private final RoleMapper roleMapper;
    private final PasswordEncoder passwordEncoder;

    /**
     * 分页查询用户信息
     *
     * @param paginationParam 分页对象
     * @param sortParam       排序对象
     * @param intervalStr     时间间隔对象
     * @param queryUserBO     查询的用户信息对象
     * @return 符合条件的用户列表
     */
    @Override
    public PaginationResult<UserBO> queryUserList(PaginationParam paginationParam, SortParam sortParam, IntervalStr intervalStr, QueryUserBO queryUserBO) {
        // 处理时间间隔
        Interval interval = ServiceUtils.getInterval(intervalStr);
        // 分页对象
        Page<User> userPage = ServiceUtils.getPage(paginationParam);
        // 构建查询条件对象
        String sortSql = "";
        if (StringUtils.hasText(sortParam.getSortField())) {
            sortSql = SortUtils.getSortSql(sortParam);
        }
        LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper
                .like(StringUtils.hasText(queryUserBO.getUsername()), User::getUsername, queryUserBO.getUsername())
                .like(StringUtils.hasText(queryUserBO.getPhone()), User::getPhone, queryUserBO.getPhone())
                .like(StringUtils.hasText(queryUserBO.getNickname()), User::getNickname, queryUserBO.getNickname())
                .like(StringUtils.hasText(queryUserBO.getEmail()), User::getEmail, queryUserBO.getEmail())
                .eq(Objects.nonNull(queryUserBO.getStatus()), User::getStatus, queryUserBO.getStatus())
                .between(StringUtils.hasText(intervalStr.getUpdatedAtStart()) && StringUtils.hasText(intervalStr.getUpdatedAtEnd()),
                        User::getUpdatedAt, interval.getUpdatedAtStart(), interval.getUpdatedAtEnd())
                .between(StringUtils.hasText(intervalStr.getCreatedAtStart()) && StringUtils.hasText(intervalStr.getCreatedAtEnd()), User::getCreatedAt, interval.getCreatedAtStart(), interval.getCreatedAtEnd())
                // 默认就是使用主键id进行升序排序，可以配置其他字段，如修改日期等
                // .orderBy(!StringUtils.hasText(sortParam.getSortOrder()), true, User::getId)
                .last(StringUtils.hasText(sortParam.getSortField()) && StringUtils.hasText(sortParam.getSortOrder()), sortSql);
        // 分页查询
        page(userPage, lambdaQueryWrapper);
        // 获取总数，如果总数为0，就直接返回
        long total = userPage.getTotal();
        if (total == 0L) {
            return PaginationResult.<UserBO>builder().total(0L).build();
        }
        // 将User转为UserBO并设置角色信息
        IPage<UserBO> convert = userPage.convert(this::getUserBO);
        List<UserBO> userBOList = convert.getRecords();
        // 如果查询的权限列表不为空，就过滤掉不服和查询条件的
        if (Objects.nonNull(queryUserBO.getRoleList()) && queryUserBO.getRoleList().size() > 0) {
            userBOList = userBOList.stream().filter(userBO -> {
                for (Long roleId : queryUserBO.getRoleList()) {
                    for (UserRole userRole : userBO.getRoleList()) {
                        if (roleId.equals(userRole.getRoleId())) {
                            return true;
                        }
                    }
                }
                return false;
            }).toList();
            total = userBOList.size();
        }
        return PaginationResult.<UserBO>builder().total(total).records(userBOList)
                .build();
    }

    /**
     * 根据用户id获取用户信息
     *
     * @param id 用户id
     * @return 用户信息
     */
    @Override
    public UserBO getUserById(Serializable id) {
        User user = getById(id);
        if (Objects.isNull(user)) {
            return null;
        }
        return getUserBO(user);
    }

    private UserBO getUserBO(User user) {
        UserBO userBO = BeanCopyUtils.copyBean(user, UserBO.class);
        List<UserRole> userRoleList = roleMapper.queryRoleListByUserId(userBO.getId());
        userBO.setRoleList(userRoleList);
        return userBO;
    }

    /**
     * 新增用户信息
     *
     * @param addUserBO 新增用户业务对象
     * @return 操作结果
     */
    @Override
    public String addUser(AddUserBO addUserBO) {
        User user = BeanCopyUtils.copyBean(addUserBO, User.class);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        boolean saved = save(user);
        if (saved) {
            log.info("新增用户成功{}", user);
            return "新增成功";
        }
        throw new RuntimeException("新增失败");
    }

    /**
     * 更新用户信息
     *
     * @param updateUserBO 跟新用户业务对象
     * @return 是否封信成功
     */
    @Override
    public String updateUser(UpdateUserBO updateUserBO) {
        User user = BeanCopyUtils.copyBean(updateUserBO, User.class);
        List<Long> roleList = updateUserBO.getRoleList();
        boolean isSuccess;
        // 先删除该用户对应的所有权限信息
        isSuccess = getBaseMapper().updateById(user) > 0 && getBaseMapper().deleteUserRole(user.getId()) >= 0;
        // 有角色信息的时候才进行添加用户角色信息的操作
        if (Objects.nonNull(roleList) && roleList.size() > 0) {
            // 再把新的用户角色对应信息插入到中间表中
            isSuccess = getBaseMapper().addUserRole(user.getId(), roleList) > 0;
        }
        if (isSuccess) {
            log.info("用户信息更新成功{}", user);
            return "更新成功";
        }
        throw new RuntimeException("更新失败");
    }

    @Override
    public List<Map<String, Long>> getUserData() {
        return getBaseMapper().getUserData();
    }

    @Override
    public List<Map<String, Long>> getUserAddData() {
        return getBaseMapper().getUserAddData();
    }

    @Override
    public List<ArticleBO> queryRentalArticle(Long userId) {
        List<Article> articleList = getBaseMapper().queryRentalArticle(userId);
        return BeanCopyUtils.copyBeanList(articleList, ArticleBO.class);
    }

    /**
     * @param userInfo 用户的某一项信息
     * @param info     提供的信息
     * @param <T>      用户信息的类型
     * @return 是否存在拥有这一个信息的用户
     */
    @Override
    public <T> boolean isExist(SFunction<User, T> userInfo, String info) {
        LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(userInfo, info);
        User user = super.getOne(lambdaUpdateWrapper);
        return user != null;
    }
}

